using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
namespace CSUtils {
    public static class CString {
        const string tag = "CString";
        public const char cSplit01 = '▅';
        public const char cSplit02 = '➜';
        public const char cSplit03 = '✪';
        public const char cSplit04 = '▌';
        public const char cSplit05 = '✚';
        public const char cSplit06 = '〓';
        public const char cSplit07 = '█';
        public const char cSplit08 = '◆';
        public const char cSplit09 = '▲';
        public const char cSplit10 = '▼';
        public const char cSplit11 = '✖';
        public const char cSplit12 = '【';
        public const char cSplit13 = '】';
        public const char cSplit16 = '⧫';
        public const char cSplit18 = '⬤';
        public const char cSplit21 = '∬';
        public const char cSplit22 = '∫';
        public const char cSplit23 = '➋';
        public const char cSplit24 = '╬';
        public const char cSplit25 = '▃';

        public const char cSplit43 = 'ↂ';
        public const char cSplit45 = '✔';
        public const char cSplit46 = '✘';
        public const char cSplit47 = '◙';
        public const char cSplit48 = '◘';
        public const char cSplit50 = '『';
        public const char cSplit51 = '』';
        public const char cSplit52 = '【';
        public const char cSplit53 = '】';
        public const char cSplit54 = '↔';
        public const char cSplit55 = '↕';

        /// <summary>					    
        /// 消除中文字符
        /// </summary>
        /// <param name="str"></param>
        /// <param name="limitLength"></param>
        /// <param name="isToLower"></param>
        /// <returns></returns>
        public static string ClearChinese(string str, int limitLength = 60, bool isToLower = true) { //chinese
            StringBuilder ssb = new StringBuilder();
            for(int i = 0; i < str.Length; i++) {
                int ii = (int)str[i];
                if(ii > 127) {
                    ssb.Append(ii);
                } else {
                    ssb.Append(str[i]);
                }
            }
            str = ssb.ToString();
            str = str.Replace("\\", "/");
            if(isToLower) {
                str = str.ToLower();
            }
            string[] sss = str.Split('/');
            if(sss.Length > 1) {
                string ssName = Path.GetFileName(str);
                if(ssName.Length > limitLength) {
                    str = str.Remove(str.Length - ssName.Length, ssName.Length);
                    ssName = ssName.Remove(0, ssName.Length - limitLength);
                    //string sss4 = Path.GetDirectoryName(ss);
                    if(ssName[0] == '.') {
                        ssName = "a_" + ssName;
                    }
                    str = str + ssName;
                    CLog.E(tag, ssName + "_长度超标__已经被限制为60______" + str);
                }
            } else {
                if(str.Length > limitLength) {
                    str = str.Remove(0, str.Length - limitLength);
                    if(str[0] == '.') {
                        str = "a_" + str;
                    }
                    CLog.E(tag, "长度超标__" + str);
                }
            }
            return str;
        }

        public static string ClearChinese0(string str, int limitLength = 60) {
            StringBuilder ssb = new StringBuilder();
            for(int i = 0; i < str.Length; i++) {
                int ii = (int)str[i];
                if(ii > 127) {
                    ssb.Append(ii);
                } else {
                    ssb.Append(str[i]);
                }
            }
            string ss2 = ssb.ToString();
            int ii3 = (int)ss2[0];
            //if(65> ii3 && ii3 < 90  || 97 > ii3 && ii3 < 122 || ss2[0]=='_') {
            //    return ss2;
            //}
            if(16 > ii3 || ii3 > 25) {
                return ss2;
            }
            return"a_" + ss2;
        }

        public static string S_EscapeURL(string ss0, int zLimit = 60, bool isToLower = true) {
            StringBuilder ssb = new StringBuilder();
            for(int i = 0; i < ss0.Length; i++) {
                int ii = (int)ss0[i];
                if(ii > 127) {
                    ssb.Append(ii);
                } else {
                    ssb.Append(ss0[i]);
                }
            }
            string ss = ssb.ToString();
            ss = ss.Replace("\\", "/");
            if(isToLower) {
                ss = ss.ToLower();
            }
            //ss = WWW.EscapeURL(ss);
            string[] sss = ss.Split('/');
            if(sss.Length > 1) {
                string ssName = Path.GetFileName(ss);
                if(ssName.Length > zLimit) {
                    string directory = ss.Remove(ss.Length - ssName.Length, ssName.Length);
                    ssName = ssName.Remove(0, ssName.Length - zLimit);
                    ss = directory + ssName;
                    CLog.E(tag, ss0 + "_长度超标__已经被限制为60______" + ss);
                }
                //ss = "";
                //for(int i = 0; i < sss.Length-1; i++) {
                //    ss += WWW.EscapeURL(sss[i]) + "/";
                //}
                //ss += WWW.EscapeURL(ssName);
            } else {
                if(ss.Length > zLimit) {
                    ss = ss.Remove(0, ss.Length - zLimit);
                    CLog.E(tag, "长度超标__" + ss);
                }
                //ss = WWW.EscapeURL(ss);
            }
            ss = ss.Replace(".", "-");
            ss = ss.Replace("@", "1");
            ss = ss.Replace("#", "2");
            ss = ss.Replace("%", "3");
            ss = ss.Replace("?", "4");
            ss = ss.Replace("&", "5");
            ss = ss.Replace("!", "6");
            ss = ss.Replace("+", "7");
            return ss;
        }

        public static int StrLength(this string str) {
            int length = 0;
            for(int i = 0; i < str.Length; i++) {
                int ii = str[i];
                if(ii > 127) {
                    length += 2;
                } else {
                    length++;
                }
            }
            return length;
        }

        /// <summary>
        /// 字符串,拆分模块---拆除前后括号--{--}-----------
        /// </summary>
        public static string[] SplitModule(this string str, string startString, string endString) {
            string[] sss = new string[3];
            int startPosi = str.IndexOf(startString);
            int endPosi = startPosi;
            int index = startPosi;
            int layer = -1;
            while(layer < 0) {
                int startPosi0 = str.IndexOf(startString, index + 1);
                int endPosi0 = str.IndexOf(endString, index + 1);
                if(startPosi0 < 0) {
                    startPosi0 = endPosi0 + 1;
                }
                if(endPosi0 <= 0) {
                    CLog.E(tag, "超级错误.sssssssssssssss");
                }
                if(startPosi0 < endPosi0) {
                    index = startPosi0;
                    layer--;
                } else {
                    index = endPosi0;
                    endPosi = index;
                    layer++;
                }
            }
            sss[0] = str.Substring(0, startPosi);
            sss[1] = str.Substring(startPosi + 1, endPosi - startPosi - 1);
            sss[2] = str.Substring(endPosi + 1, str.Length - endPosi - 1);
            return sss;
        }

        /// <summary>
        /// 目录名显示长度限制
        /// </summary>
        public static string DirNameLengthLimit(this string dirPath, int lenLimit) {
            if(dirPath.Length > lenLimit) {
                int len = lenLimit / 2;
                string start = dirPath.Substring(0, len);
                string end = dirPath.Substring(dirPath.Length - len, len);
                return$"{start}-***-{end}";
            }
            return dirPath;
        }

        public static string GetMD5(this string ss) {
            byte[] bytes = Encoding.UTF8.GetBytes(ss);
            return GetMD5(bytes);
        }

        public static string GetMD5(this byte[] bytes) {
            using(MD5 m5 = MD5.Create()) {
                bytes = m5.ComputeHash(bytes);
                m5.Clear();
                StringBuilder ssb = new StringBuilder();
                for(int i = 0; i < bytes.Length; i++) {
                    ssb.Append(bytes[i].ToString("x2"));
                }
                return ssb.ToString();
            }
        }

        public static string HashToMD5Hex(this string ss) {
            byte[] bytes = Encoding.UTF8.GetBytes(ss);
            return HashToMD5Hex(bytes);
        }

        public static string HashToMD5Hex(this byte[] bytes) {
            using(MD5CryptoServiceProvider m5 = new MD5CryptoServiceProvider()) {
                bytes = m5.ComputeHash(bytes);
                StringBuilder ssb = new StringBuilder();
                for(int i = 0; i < bytes.Length; i++) {
                    ssb.Append(bytes[i].ToString("x2"));
                }
                m5.Clear();
                return ssb.ToString();
            }
        }

        public static string GetStrInNumber(string str) {
            if(string.IsNullOrEmpty(str)) {
                return str;
            }
            var sb = new StringBuilder();
            for(int i = 0; i < str.Length; i++) {
                int cc = str[i];
                if(cc >= 48 && cc < 58) {
                    sb.Append(str[i]);
                }
            }
            return sb.ToString();
        }

        public static string SetColor(this string str, string colorStr, int fontSize) {
            return$"<size={fontSize}>{str.SetColor(colorStr)}</size>";
        }

        /// <summary>
        /// z颜色='ffff00'
        /// </summary>
        /// <param name="colorText='ffff00'"></param>
        public static string SetColor(this string str, string colorStr) {
            int index = str.IndexOf('\n');
            if(index > 0) {
                int index2 = str.IndexOf('\n', index + 1);
                if(index2 > index) {
                    str = str.Insert(index2, " </color> ");
                    str = $"<color=#{colorStr}> {str}";
                } else {
                    index = -1;
                }
            } else {
                str = $"<color=#{colorStr}>{str}</color>";
            }
            return str;
        }

        public static string SetColor(this string str, int fontSize) {
            return$"<size={fontSize}>{str}</size>";
        }

        public static string SetLogColor(this string str, string colorText) {
            return$"#{colorText}#{str}";
        }

        public static string GetLogColor(this string log, out string colorText) {
            colorText = null;
            if(log == null) {
                return log;
            }
            var len = log.Length;
            if(len > 8 && log[0] == '#' && log[7] == '#') {
                colorText = log.Substring(1, 6);
                log = log.Substring(8);
                return log;
            }
            return log;
        }

        /// <summary>
        /// 两位数时间 2天21小时
        /// </summary>
        public static string TimeToStr(this float _second, string dayTag = "d", string hourTag = "h", string minTag = "m", string secondTag = "s", string textColor = null) {
            return TimeToStr((int)_second, dayTag, hourTag, minTag, secondTag, textColor);
        }

        /// <summary>
        /// 两位数时间 2天21小时
        /// </summary>
        public static string TimeToStr(this int _second, string dayTag = "d", string hourTag = "h", string minTag = "m", string secondTag = "s", string textColor = null) {
            string ss = "";
            int day = _second / 86400;
            int hour = (_second % 86400) / 3600;
            int min = (_second % 3600) / 60;
            int second = (_second % 60);
            if(day > 0) {
                ss = $"<color=#{textColor}>{day}</color>{dayTag}";
                if(hour > 0) {
                    ss = $"<color=#{textColor}>{hour}</color>{hourTag}";
                }
            } else {
                if(hour > 0) {
                    ss = $"<color=#{textColor}>{hour}</color>{hourTag}";
                    if(min > 0) {
                        ss = $"<color=#{textColor}>{min}</color>{minTag}";
                    }
                } else {
                    if(min > 0) {
                        ss = $"<color=#{textColor}>{min}</color>{minTag}";
                        if(second > 0) {
                            ss = $"<color=#{textColor}>{second}</color>{secondTag}";
                        }
                    } else {
                        if(second > 0) {
                            ss = $"<color=#{textColor}>{second}</color>{secondTag}";
                        } else {
                            ss = $"<color=#{textColor}>{0}</color>{secondTag}";
                        }
                    }
                }
            }
            return ss;
        }

        public static string TimeDayToStr(long _hours, long _minutes, long _seconds, string colorStr, int fontSize, string hoursTag = "时", string minutesTag = "分", string secondsTag = "秒") {
            var ssb = new StringBuilder();
            if(_hours > 0) {
                ssb.Append($"<size={fontSize}><color=#{colorStr}>{_hours}</color></size>{hoursTag}");
            }
            if(_hours > 0 || _minutes > 0) {
                ssb.Append($"<size={fontSize}><color=#{colorStr}>{_minutes}</color></size>{minutesTag}");
            }
            if(_seconds > 0) {
                ssb.Append($"<size={fontSize}><color=#{colorStr}>{_seconds}</color></size>{secondsTag}");
            }
            return ssb.ToString();
        }

        public static string TimeToHourStr2(double _second, string hourTag = "时", string minTag = "分", string secondTag = "秒") {
            return TimeToHourStr((int)_second, hourTag, minTag, secondTag);
        }

        public static string TimeToHourStr(double _second, string hourTag = "h", string minTag = "m", string secondTag = "s") {
            return TimeToHourStr((int)_second, hourTag, minTag, secondTag);
        }

        public static string TimeToHourStr(long _second, string hourTag = "h", string minTag = "m", string secondTag = "s") {
            return TimeToHourStr((int)_second, hourTag, minTag, secondTag);
        }

        /// <summary>
        /// 时.分.秒.的时间
        /// </summary>
        public static string TimeToHourStr(this int _second, string hourTag = "h", string minTag = "m", string secondTag = "s") {
            int hour = _second / 3600;
            int min = (_second % 3600) / 60;
            int second = (_second % 60);
            string timeStr = "";
            if(hour > 0) {
                timeStr = $"{hour}{hourTag}{min}{minTag}{second}{secondTag}";
            } else {
                if(min > 0) {
                    timeStr = $"{min}{minTag}{second}{secondTag}";
                } else {
                    timeStr = $"{second}{secondTag}";
                }
            }
            return timeStr;
        }

        public static string GetGameTimeStr(float timeToDisplay, string strFormat = null) {
            return GetGameTimeStr(CMathf.RoundToInt(timeToDisplay), strFormat);
        }

        public static string GetGameTimeStr(int timeToDisplay, string strFormat = null) {
            int minutes = timeToDisplay / 60;
            int seconds = timeToDisplay % 60;
            string timeStr = "";
            if(string.IsNullOrEmpty(strFormat)) {
                timeStr = string.Format("{0:00}:{1:00}", minutes, seconds);
            } else {
                timeStr = string.Format(strFormat, minutes, seconds);
            }

            return timeStr;
        }

        public static string NumberToStr(this float value, string format = "0") {
            if(value < 0) {
                return value.ToString("0.000");
            } else if(value < 10) {
                return value.ToString("0.00");
            } else if(value < 100) {
                return value.ToString("0.0");
            } else {
                return NumberToStr((double)value, format);
            }
        }

        public static string NumberToStr(this int value, string format = "0") {
            return NumberToStr((double)value);
        }

        public static string NumberToStr(this long value, string format = "0") {
            return NumberToStr((double)value);
        }

        /// <summary>
        /// K,M,G,T,P,E,B
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string NumberToStr(this double value, string format = "0") {
            if(value < 1000) {
                return value.ToString(format);
            }
            string ss = value.ToString("0");
            int z缩进位数 = ss.Length / 3;
            int z缩进标准长度 = z缩进位数 * 3;
            int z多余长度 = ss.Length - z缩进标准长度;
            switch(z多余长度) {
                case 0: //
                    return ss.Substring(0, 3) + GetVs[z缩进位数 - 2]; //
                case 1: //
                    return ss.Substring(0, 3).Insert(1, ".") + GetVs[z缩进位数 - 1];
                case 2: //
                    return ss.Substring(0, 3).Insert(2, ".") + GetVs[z缩进位数 - 1];
            }
            return"rrro";
        }

        static char[] GetVs = new[] { 'K', 'M', 'G', 'T', 'P', 'E', 'B', 'O', 'W', 'Y', 'X', 'U', 'N' };

        public static string NumberToStr2(this double value, string format = "0") {
            var value0 = value;
            if(value < 10000) { //万
                // if(value < 100) {
                //     return value.ToString("0.00");
                // }
                // if(value < 1000) {
                //     return value.ToString("0.0");
                // }
                return value.ToString("0");
            }
            if(value < 100000000) { //亿
                value0 = value / 10000f;
                if(value0 < 100) {
                    return value0.ToString("0万");
                }
                if(value0 < 1000) {
                    return value0.ToString("0.0万");
                }
                return value0.ToString("0.00万");
            }
            value0 = value / 100000000;
            if(value0 < 100) {
                return value0.ToString("0亿");
            }
            if(value0 < 1000) {
                return value0.ToString("0.0亿");
            }
            return value0.ToString("0.00亿");
        }

        public const long cKB = 1024;
        public const long cMB = 1024 * 1024;
        public const long cGB = 1024 * 1024 * 1024;

        public static string GetFileSizeStr(this long fileZise) {
            if(fileZise > cGB) {
                return(fileZise * 1f / cGB).ToString("0.00") + "GB";
            } else if(fileZise > cMB) {
                return(fileZise * 1f / cMB).ToString("0.00") + "MB";
            } else if(fileZise > cKB) {
                return(fileZise * 1f / cKB).ToString("0.00") + "KB";
            }
            return fileZise + "B";
        }

        public static string ToStr<T>(this T[] array, Func<T, object> objToStrEvent) {
            return ToStr<T>(array, ",_", objToStrEvent);
        }

        public static string ToStr<T>(this T[] arr, string cut = ",_", Func<T, object> objToStrEvent = null) {
            if(arr == null) {
                return"null";
            }
            if(arr.Length == 0) {
                return"len=0";
            }
            var ssb = new StringBuilder();
            for(int ii = 0; ii < arr.Length; ii++) {
                var obj = arr[ii];
                var objStr = "";
                if(objToStrEvent == null || obj == null) {
                    objStr = obj == null? "null": obj.ToString();
                } else {
                    objStr = objToStrEvent.Invoke(obj).ToString();
                }
                if(ii == 0) {
                    ssb.Append(objStr);
                } else {
                    ssb.Append($"{cut}{objStr}");
                }
            }
            return ssb.ToString();
        }

        public static string ToAAStr<T>(this T[][] arrArr, Func<T, object> objToStrEvent = null, string split1Str = ",", string split2Str = "/") {
            if(arrArr == null || arrArr.Length == 0) {
                return"null";
            }
            var ssb = new StringBuilder();
            for(int i2 = 0; i2 < arrArr.Length; i2++) {
                if(i2 != 0) {
                    ssb.Append(split2Str);
                }
                var arr = arrArr[i2];
                for(int i3 = 0; i3 < arr.Length; i3++) {
                    var obj = arr[i3];
                    var objStr = "";
                    if(objToStrEvent == null) {
                        objStr = obj == null? "null": obj.ToString();
                    } else {
                        objStr = objToStrEvent.Invoke(obj).ToString();
                    }
                    if(i3 == 0) {
                        ssb.Append(objStr);
                    } else {
                        ssb.Append($"{split1Str}{objStr}");
                    }
                }
            }

            string ss = ssb.ToString();
            return ss;
        }

        public static string ToStr<T>(this List<T> list, Func<T, object> objToStrEvent = null) {
            if(list == null || list.Count == 0) {
                return"null";
            }
            var ssb = new StringBuilder();
            for(int ii = 0; ii < list.Count; ii++) {
                object obj = list[ii];
                if(objToStrEvent != null) {
                    obj = objToStrEvent(list[ii]);
                }
                if(ii == 0) {
                    ssb.AppendFormat("{0}", obj);
                } else {
                    ssb.AppendFormat(",_{0}", obj);
                }
            }
            return ssb.ToString();
        }

        public static string ToStr<T>(this IEnumerable<T> list, Func<T, object> objToStrEvent = null) {
            if(list == null) {
                return"null";
            }
            bool isStart = true;
            var ssb = new StringBuilder();
            var et = list.GetEnumerator();
            while(et.MoveNext()) {
                object obj = et.Current;
                if(objToStrEvent != null) {
                    obj = objToStrEvent(et.Current);
                }
                if(isStart) {
                    ssb.AppendFormat("{0}", obj);
                } else {
                    ssb.AppendFormat(",_{0}", obj);
                }
                isStart = false;
            }
            return ssb.ToString();
        }

        public static string ToStr<T>(this List<List<T>> list, Func<T, object> objToStrEvent = null) {
            if(list == null || list.Count == 0) {
                return"null";
            }
            StringBuilder ssb = new StringBuilder();
            for(int i = 0; i < list.Count; i++) {
                if(i != 0) {
                    ssb.Append("+");
                }
                for(int ii = 0; ii < list[i].Count; ii++) {
                    object obj = list[i][ii];
                    if(objToStrEvent != null) {
                        obj = objToStrEvent(list[i][ii]);
                    }
                    if(ii == 0) {
                        ssb.AppendFormat("{0}", obj);
                    } else {
                        ssb.AppendFormat(",_{0}", obj);
                    }
                }
            }
            string ss = ssb.ToString();
            if(list.Count > 1) {
                ss = ss.Substring(0, ss.Length - 1);
            }
            return ss;
        }

        public static string ToStr<T, V>(this Dictionary<T, V> dic0, Func<V, object> objToStrEvent = null) {
            if(dic0 == null || dic0.Count == 0) {
                return"null";
            }
            Type typeV = typeof(V);
            bool isClass = typeV.IsClass;
            isClass = (typeV != typeof(object) && isClass);
            var ssb = new StringBuilder();
            int ii = 0;
            var dic = dic0.GetEnumerator();
            while(dic.MoveNext()) {
                object value = 0;
                if(objToStrEvent != null) {
                    value = objToStrEvent(dic.Current.Value);
                } else {
                    if(isClass) {
                        value = "obj";
                    } else {
                        value = dic.Current.Value;
                    }
                }
                if(ii == 0) {
                    ssb.Append($"{dic.Current.Key}={value}");
                } else {
                    ssb.Append($",_{dic.Current.Key}={value}");
                }
                ii++;
            }
            return ssb.ToString();
        }

        /// <summary>
        /// S_10进制到62进制
        /// </summary>
        /// <param name="number"></param>
        /// <returns></returns>
        public static string S_Hex10ToHex62(this Int64 number) {
            int binary62 = 62;
            byte[] bytes = new byte[20];
            int i = 0;
            while(number != 0) {
                i++;
                bytes[bytes.Length - i] = byte.Parse((number % binary62).ToString());
                number /= binary62;
            }
            //0=0,A=36,a=10
            //0=48,A=65,a=97
            string str = "";
            for(int i2 = bytes.Length - i; i2 < bytes.Length; i2++) {
                str += " " + bytes[i2];
                if(bytes[i2] < 10) {
                    bytes[i2] = byte.Parse((bytes[i2] + 48).ToString());
                } else if(bytes[i2] < 36) {
                    bytes[i2] = byte.Parse((bytes[i2] + 87).ToString());
                } else {
                    bytes[i2] = byte.Parse((bytes[i2] + 29).ToString());
                }
            }
            return System.Text.Encoding.UTF8.GetString(bytes, bytes.Length - i, i);
        }

        public static Int64 S_Hex62ToHex10(this string str) {
            int binary62 = 62;
            long ll = 0;
            byte[] bytes = Encoding.UTF8.GetBytes(str);
            for(int i = 0; i < bytes.Length; i++) {
                if(bytes[i] > 96) {
                    bytes[i] = byte.Parse((bytes[i] - 87).ToString());
                } else if(bytes[i] > 64) {
                    bytes[i] = byte.Parse((bytes[i] - 29).ToString());
                } else {
                    bytes[i] = byte.Parse((bytes[i] - 48).ToString());
                }
                ll += bytes[i] * (long)Math.Pow(binary62, bytes.Length - i - 1);
            }
            return ll;
        }

        public static string S_Hex10ToHex36(this int number) {
            int binary36 = 36;
            byte[] bytes = new byte[20];
            int i = 0;
            while(number != 0) {
                i++;
                bytes[bytes.Length - i] = byte.Parse((number % binary36).ToString());
                number /= binary36;
            }
            //0=0,A=36,a=10
            //0=48,A=65,a=97
            string str = "";
            for(int i2 = bytes.Length - i; i2 < bytes.Length; i2++) {
                str += " " + bytes[i2];
                if(bytes[i2] > 9) {
                    bytes[i2] = byte.Parse((bytes[i2] + 87).ToString());
                } else {
                    bytes[i2] = byte.Parse((bytes[i2] + 48).ToString());
                }
            }
            return System.Text.Encoding.UTF8.GetString(bytes, bytes.Length - i, i);
        }

        public static int S_Hex36ToHex10(this string ss) {
            int binary36 = 36;
            int number = 0;
            byte[] bytes = Encoding.UTF8.GetBytes(ss);
            //0=0,A=36,a=10
            //0=48,A=65,a=97
            for(int i = 0; i < bytes.Length; i++) {
                if(bytes[i] > 96) {
                    bytes[i] = byte.Parse((bytes[i] - 87).ToString());
                } else {
                    bytes[i] = byte.Parse((bytes[i] - 48).ToString());
                }
                number += bytes[i] * (int)Math.Pow(binary36, bytes.Length - i - 1);
            }
            return number;
        }

        /// <summary>
        /// 获取Excel csv的数据
        /// </summary>
        /// <param name="str"></param>
        /// <param name="dic"></param>
        public static void GetExcelCSVData(this string str, Dictionary<int, string[]> dic) {
            string[] lineArr = str.Split('\n');
            for(int i = 0; i < lineArr.Length; i++) {
                try {
                    string[] arr = lineArr[i].Split('\t');
                    int ii = int.Parse(arr[0]);
                    dic[ii] = arr;
                } catch(Exception ex) {
                    CLog.E(tag, "解析出错_" + lineArr[i] + "\n_" + ex.GetInfo());
                }
            }
        }

        /// <summary>
        /// 是否匹配
        /// </summary>
        /// <param name="path" ></param>
        /// <param name="matchingArr"></param>
        /// <param name="matchingType">1=StartsWith, 2=EndsWith, 3=Contains </param>
        /// <returns></returns>
        public static bool IsMatching(this string path, string[] matchingArr, EMatchingType matchingType) {
            if(matchingArr == null) {
                return false;
            }
            string matching = path.Matching(matchingArr, matchingType);
            return matching != null;
        }

        /// <summary>
        /// 是否匹配
        /// </summary>
        /// <param name="path" ></param>
        /// <param name="matchingArr"></param>
        /// <param name="matchingType">1=StartsWith, 2=EndsWith, 3=Contains </param>
        /// <returns></returns>
        public static string Matching(this string path, string[] matchingArr, EMatchingType matchingType) {
            if(path == null) {
                return null;
            }
            if(matchingArr == null || matchingArr.Length == 0) {
                return null;
            }
            for(int i4 = 0; i4 < matchingArr.Length; i4++) {
                switch(matchingType) {
                    case EMatchingType.StartsWith:
                        if(path.StartsWith(matchingArr[i4], StringComparison.Ordinal)) {
                            return matchingArr[i4];
                        }
                        break;
                    case EMatchingType.EndsWith:
                        if(path.EndsWith(matchingArr[i4], StringComparison.Ordinal)) {
                            return matchingArr[i4];
                        }
                        break;
                    case EMatchingType.Contains:
                        if(path.Contains(matchingArr[i4])) {
                            return matchingArr[i4];
                        }
                        break;
                    case EMatchingType.Equal:
                        if(path == matchingArr[i4]) {
                            return matchingArr[i4];
                        }
                        break;
                }
            }
            return null;
        }

        public static string DirFormat(this string dir, int type) {
            if(string.IsNullOrEmpty(dir)) {
                return dir;
            }
            dir = dir.Replace("\\", "/");
            return StrFormat(dir, type, "/");
        }

        public static string StrFormat(this string dir, int type, string format) {
            if(string.IsNullOrEmpty(dir)) {
                return dir;
            }
            switch(type) {
                case 1: //-----"dir"
                    if(dir.StartsWith(format, StringComparison.Ordinal)) {
                        dir = dir.Substring(format.Length);
                    }
                    if(dir.EndsWith(format, StringComparison.Ordinal)) {
                        dir = dir.Substring(0, dir.Length - format.Length);
                    }
                    break;
                case 2: //-----"/dir"	 
                    if(dir.StartsWith(format, StringComparison.Ordinal) == false) {
                        dir = format + dir;
                    }
                    if(dir.EndsWith(format, StringComparison.Ordinal)) {
                        dir = dir.Substring(0, dir.Length - format.Length);
                    }
                    break;
                case 3: //-----"dir/"
                    if(dir.StartsWith(format, StringComparison.Ordinal)) {
                        dir = dir.Substring(format.Length);
                    }
                    if(dir.EndsWith(format, StringComparison.Ordinal) == false) {
                        dir = dir + format;
                    }
                    break;
                case 4: //-----"/dir/"
                    if(dir.StartsWith(format, StringComparison.Ordinal) == false) {
                        dir = format + dir;
                    }
                    if(dir.EndsWith(format, StringComparison.Ordinal) == false) {
                        dir = dir + format;
                    }
                    break;
            }
            return dir;
        }

        public static string SetWWWPath(this string path) {
            #if UNITY_ANDROID && !UNITY_EDITOR
            path = path.StrFormat(1, "file://");
            #else
            path = path.StrFormat(2, "file://");
            #endif
            return path;
        }

        /// <summary>
        /// 中文转换为UniCode符号
        /// </summary>  
        public static string Unicode_Escape(string str) {
            string result = "";
            for(int i = 0; i < str.Length; i++) {
                if(str[i] > 32 && str[i] < 127) {
                    result += str[i].ToString();
                } else {
                    result += string.Format("\\u{0:x4}", (int)str[i]);
                }
            }
            return result;
        }

        /// <summary>
        /// UniCode符号转换为中文
        /// </summary>  
        public static string Unicode_Unescape(string str) {
            return Regex.Unescape(str);
            return new Regex(@"\\u([0-9A-F]{4})", RegexOptions.IgnoreCase).Replace(str, x=>string.Empty + Convert.ToChar(Convert.ToUInt16(x.Result("$1"), 16)));
        }

        public static string STrim(this string str) {
            str = str.Trim();
            var _str = str;
            if(str.StartsWith("'", StringComparison.Ordinal) && str.EndsWith("'", StringComparison.Ordinal)) {
                _str = _str.Substring(1, _str.Length - 2);
            } else if(str.StartsWith("\"", StringComparison.Ordinal) && str.EndsWith("\"", StringComparison.Ordinal)) {
                _str = _str.Substring(1, _str.Length - 2);
            }
            return _str;
        }

        /// <summary>
        /// CString.GetTimeStamp(2254484848,"yyyy年MM月dd日::HH时:mm分:ss秒");
        /// </summary> 
        public static string GetTimeStamp(double timeStamp, string format) {
            try {
                DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); //当地时区
                var time = startTime.AddSeconds(timeStamp);
                var timeStr = time.ToString(format);
                return timeStr;
            } catch(Exception ex) {
                CLog.Ex(tag, $"时间解析错误.....{timeStamp}", ex);
            }
            return"-000";
        }

        /// <summary>
        /// 去除文件bom头后的字符
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        public static string GetUTF8String(byte[] buffer) {
            if(buffer == null) {
                return null;
            }
            if(buffer.Length <= 3) {
                return Encoding.UTF8.GetString(buffer);
            }
            byte[] bomBuffer = new byte[] { 0xef, 0xbb, 0xbf };
            if(buffer[0] == bomBuffer[0] && buffer[1] == bomBuffer[1] && buffer[2] == bomBuffer[2]) {
                return new UTF8Encoding(false).GetString(buffer, 3, buffer.Length - 3);
            }
            return Encoding.UTF8.GetString(buffer);
        }

        public static string GetMd5(string input) {
            MD5 md5Hasher = MD5.Create();
            byte[] data = md5Hasher.ComputeHash(Encoding.Default.GetBytes(input));
            var sBuilder = new StringBuilder();
            for(int i = 0; i < data.Length; i++) {
                sBuilder.Append(data[i].ToString("x2"));
            }
            return sBuilder.ToString();
        }

        public static bool StartsWith(this string str, char c) {
            if(string.IsNullOrEmpty(str)) {
                return false;
            }
            return str[0] == c;
        }

        public static bool EndsWith(this string str, char c) {
            if(string.IsNullOrEmpty(str)) {
                return false;
            }
            return str[str.Length - 1] == c;
        }

        public static string ToLowerX(this string str) {
            //A-Z.....65-90
            //a-z.....97-122
            var ssb = new StringBuilder();
            for(int i = 0; i < str.Length; i++) {
                var c = str[i];
                if(c >= 65 && c <= 90) {
                    ssb.Append((char)(c + 32));
                } else {
                    ssb.Append(c);
                }
            }
            return ssb.ToString();
        }

        public static bool IsNull(this string value) {
            return value == null || 0U >= (uint)value.Length;
        }

        public static bool IsNoNull(this string value) {
            return value != null && 0U < (uint)value.Length;
        }

        public static string Formats(this string value, params object[] paraArr) {
            if(value == null || 0U >= (uint)value.Length) {
                return value;
            }
            return string.Format(value, paraArr);
        }

        public static string Format(this string value, params object[] paraArr) {
            if(value == null || 0U >= (uint)value.Length) {
                return value;
            }
            return string.Format(value, paraArr);
        }

        public static string DirFormat(this string dir, params object[] paraArr) {
            if(dir.IsNull()) {
                return dir;
            }
            dir = dir.Replace('\\', '/');

            bool _Format() {
                var index = dir.IndexOf("/..", StringComparison.Ordinal);
                if(index > 0) {
                    var index2 = dir.LastIndexOf('/', index - 1);
                    dir = dir.Remove(index2, index - index2 + 3);
                    return true;
                }
                return false;
            }

            while(_Format()) {}

            return dir;
        }
    }

    public enum EMatchingType {
        StartsWith = 1, //
        EndsWith = 2, //
        Contains = 3, //
        Equal = 4, //
    }
}
